home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / admin / dig-2.0 / dig-2 / dig.2.0 / res_comp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-04  |  6.7 KB  |  322 lines

  1.  
  2. /*
  3.  * Copyright (c) 1985 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted
  7.  * provided that this notice is preserved and that due credit is given
  8.  * to the University of California at Berkeley. The name of the University
  9.  * may not be used to endorse or promote products derived from this
  10.  * software without specific prior written permission. This software
  11.  * is provided ``as is'' without express or implied warranty.
  12.  */
  13.  
  14. /*
  15. ** Distributed with 'dig' version 2.0 from University of Southern
  16. ** California Information Sciences Institute (USC-ISI). 9/1/90
  17. */
  18.  
  19. #if defined(LIBC_SCCS) && !defined(lint)
  20. static char sccsid[] = "@(#)res_comp.c    6.13 (Berkeley) 3/13/88";
  21. #endif /* LIBC_SCCS and not lint */
  22.  
  23. #include "hfiles.h"
  24.  
  25. #include <sys/types.h>
  26. #include <stdio.h>
  27. #include NAMESERH
  28. #ifndef T_TXT
  29. #define T_TXT 16
  30. #endif T_TXT
  31.  
  32.  
  33. /*
  34.  * Expand compressed domain name 'comp_dn' to full domain name.
  35.  * 'msg' is a pointer to the begining of the message,
  36.  * 'eomorig' points to the first location after the message,
  37.  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  38.  * Return size of compressed name or -1 if there was an error.
  39.  */
  40. dn_expand(msg, eomorig, comp_dn, exp_dn, length)
  41.     u_char *msg, *eomorig, *comp_dn, *exp_dn;
  42.     int length;
  43. {
  44.     register u_char *cp, *dn;
  45.     register int n, c;
  46.     u_char *eom;
  47.     int len = -1, checked = 0;
  48.  
  49.     dn = exp_dn;
  50.     cp = comp_dn;
  51.     eom = exp_dn + length - 1;
  52.     /*
  53.      * fetch next label in domain name
  54.      */
  55.     while (n = *cp++) {
  56.         /*
  57.          * Check for indirection
  58.          */
  59.         switch (n & INDIR_MASK) {
  60.         case 0:
  61.             if (dn != exp_dn) {
  62.                 if (dn >= eom)
  63.                     return (-1);
  64.                 *dn++ = '.';
  65.             }
  66.             if (dn+n >= eom)
  67.                 return (-1);
  68.             checked += n + 1;
  69.             while (--n >= 0) {
  70.                 if ((c = *cp++) == '.') {
  71.                     if (dn+n+1 >= eom)
  72.                         return (-1);
  73.                     *dn++ = '\\';
  74.                 }
  75.                 *dn++ = c;
  76.                 if (cp >= eomorig)    /* out of range */
  77.                     return(-1);
  78.             }
  79.             break;
  80.  
  81.         case INDIR_MASK:
  82.             if (len < 0)
  83.                 len = cp - comp_dn + 1;
  84.             cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
  85.             if (cp < msg || cp >= eomorig)    /* out of range */
  86.                 return(-1);
  87.             checked += 2;
  88.             /*
  89.              * Check for loops in the compressed name;
  90.              * if we've looked at the whole message,
  91.              * there must be a loop.
  92.              */
  93.             if (checked >= eomorig - msg)
  94.                 return (-1);
  95.             break;
  96.  
  97.         default:
  98.             return (-1);            /* flag error */
  99.         }
  100.     }
  101.     *dn = '\0';
  102.     if (len < 0)
  103.         len = cp - comp_dn;
  104.     return (len);
  105. }
  106.  
  107. /*
  108.  * Compress domain name 'exp_dn' into 'comp_dn'.
  109.  * Return the size of the compressed name or -1.
  110.  * 'length' is the size of the array pointed to by 'comp_dn'.
  111.  * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
  112.  * is a pointer to the beginning of the message. The list ends with NULL.
  113.  * 'lastdnptr' is a pointer to the end of the arrary pointed to
  114.  * by 'dnptrs'. Side effect is to update the list of pointers for
  115.  * labels inserted into the message as we compress the name.
  116.  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  117.  * is NULL, we don't update the list.
  118.  */
  119. dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
  120.     u_char *exp_dn, *comp_dn;
  121.     int length;
  122.     u_char **dnptrs, **lastdnptr;
  123. {
  124.     register u_char *cp, *dn;
  125.     register int c, l;
  126.     u_char **cpp, **lpp, *sp, *eob;
  127.     u_char *msg;
  128.  
  129.     dn = exp_dn;
  130.     cp = comp_dn;
  131.     eob = cp + length;
  132.     if (dnptrs != NULL) {
  133.         if ((msg = *dnptrs++) != NULL) {
  134.             for (cpp = dnptrs; *cpp != NULL; cpp++)
  135.                 ;
  136.             lpp = cpp;    /* end of list to search */
  137.         }
  138.     } else
  139.         msg = NULL;
  140.     for (c = *dn++; c != '\0'; ) {
  141.         /* look to see if we can use pointers */
  142.         if (msg != NULL) {
  143.             if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
  144.                 if (cp+1 >= eob)
  145.                     return (-1);
  146.                 *cp++ = (l >> 8) | INDIR_MASK;
  147.                 *cp++ = l % 256;
  148.                 return (cp - comp_dn);
  149.             }
  150.             /* not found, save it */
  151.             if (lastdnptr != NULL && cpp < lastdnptr-1) {
  152.                 *cpp++ = cp;
  153.                 *cpp = NULL;
  154.             }
  155.         }
  156.         sp = cp++;    /* save ptr to length byte */
  157.         do {
  158.             if (c == '.') {
  159.                 c = *dn++;
  160.                 break;
  161.             }
  162.             if (c == '\\') {
  163.                 if ((c = *dn++) == '\0')
  164.                     break;
  165.             }
  166.             if (cp >= eob)
  167.                 return (-1);
  168.             *cp++ = c;
  169.         } while ((c = *dn++) != '\0');
  170.         /* catch trailing '.'s but not '..' */
  171.         if ((l = cp - sp - 1) == 0 && c == '\0') {
  172.             cp--;
  173.             break;
  174.         }
  175.         if (l <= 0 || l > MAXLABEL)
  176.             return (-1);
  177.         *sp = l;
  178.     }
  179.     if (cp >= eob)
  180.         return (-1);
  181.     *cp++ = '\0';
  182.     return (cp - comp_dn);
  183. }
  184.  
  185. /*
  186.  * Skip over a compressed domain name. Return the size or -1.
  187.  */
  188. dn_skipname(comp_dn, eom)
  189.     u_char *comp_dn, *eom;
  190. {
  191.     register u_char *cp;
  192.     register int n;
  193.  
  194.     cp = comp_dn;
  195.     while (cp < eom && (n = *cp++)) {
  196.         /*
  197.          * check for indirection
  198.          */
  199.         switch (n & INDIR_MASK) {
  200.         case 0:        /* normal case, n == len */
  201.             cp += n;
  202.             continue;
  203.         default:    /* illegal type */
  204.             return (-1);
  205.         case INDIR_MASK:    /* indirection */
  206.             cp++;
  207.         }
  208.         break;
  209.     }
  210.     return (cp - comp_dn);
  211. }
  212.  
  213. /*
  214.  * Search for expanded name from a list of previously compressed names.
  215.  * Return the offset from msg if found or -1.
  216.  * dnptrs is the pointer to the first name on the list,
  217.  * not the pointer to the start of the message.
  218.  */
  219. static
  220. dn_find(exp_dn, msg, dnptrs, lastdnptr)
  221.     u_char *exp_dn, *msg;
  222.     u_char **dnptrs, **lastdnptr;
  223. {
  224.     register u_char *dn, *cp, **cpp;
  225.     register int n;
  226.     u_char *sp;
  227.  
  228.     for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
  229.         dn = exp_dn;
  230.         sp = cp = *cpp;
  231.         while (n = *cp++) {
  232.             /*
  233.              * check for indirection
  234.              */
  235.             switch (n & INDIR_MASK) {
  236.             case 0:        /* normal case, n == len */
  237.                 while (--n >= 0) {
  238.                     if (*dn == '\\')
  239.                         dn++;
  240.                     if (*dn++ != *cp++)
  241.                         goto next;
  242.                 }
  243.                 if ((n = *dn++) == '\0' && *cp == '\0')
  244.                     return (sp - msg);
  245.                 if (n == '.')
  246.                     continue;
  247.                 goto next;
  248.  
  249.             default:    /* illegal type */
  250.                 return (-1);
  251.  
  252.             case INDIR_MASK:    /* indirection */
  253.                 cp = msg + (((n & 0x3f) << 8) | *cp);
  254.             }
  255.         }
  256.         if (*dn == '\0')
  257.             return (sp - msg);
  258.     next:    ;
  259.     }
  260.     return (-1);
  261. }
  262.  
  263. /*
  264.  * Routines to insert/extract short/long's. Must account for byte
  265.  * order and non-alignment problems. This code at least has the
  266.  * advantage of being portable.
  267.  *
  268.  * used by sendmail.
  269.  */
  270.  
  271. u_short
  272. _getshort(msgp)
  273.     u_char *msgp;
  274. {
  275.     register u_char *p = (u_char *) msgp;
  276. #ifdef vax
  277.     /*
  278.      * vax compiler doesn't put shorts in registers
  279.      */
  280.     register u_long u;
  281. #else
  282.     register u_short u;
  283. #endif
  284.  
  285.     u = *p++ << 8;
  286.     return ((u_short)(u | *p));
  287. }
  288.  
  289. u_long
  290. _getlong(msgp)
  291.     u_char *msgp;
  292. {
  293.     register u_char *p = (u_char *) msgp;
  294.     register u_long u;
  295.  
  296.     u = *p++; u <<= 8;
  297.     u |= *p++; u <<= 8;
  298.     u |= *p++; u <<= 8;
  299.     return (u | *p);
  300. }
  301.  
  302.  
  303. putshort(s, msgp)
  304.     register u_short s;
  305.     register u_char *msgp;
  306. {
  307.  
  308.     msgp[1] = s;
  309.     msgp[0] = s >> 8;
  310. }
  311.  
  312. putlong(l, msgp)
  313.     register u_long l;
  314.     register u_char *msgp;
  315. {
  316.  
  317.     msgp[3] = l;
  318.     msgp[2] = (l >>= 8);
  319.     msgp[1] = (l >>= 8);
  320.     msgp[0] = l >> 8;
  321. }
  322.